package com.csw.android.player.base

import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.widget.FrameLayout
import android.widget.SeekBar
import android.widget.TextView
import androidx.core.view.isVisible
import androidx.lifecycle.Observer
import com.csw.android.dev_utils.ex.ViewEx.gone
import com.csw.android.dev_utils.ex.ViewEx.visible
import com.csw.android.player.ui.dialog.SurfaceSettingDialog

/**
 * 抽象媒体控制器，此类定义媒体控制器基础能力，相关控制组件子类可以选择性实现
 */
abstract class AbsMediaControllerView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : FrameLayout(context, attrs) {

    /**用户是否在操作控制器，在通过事件分发方法中判断只要有用户按下到松开前都属于控制中，此时不该隐藏控制器导致控制中断*/
    private var inUserControl = false
        //用户正在操作控制器
        set(value) {
            if (field == value) {
                return
            }
            field = value
            checkAutoHide()
        }

    /**自动隐藏延时*/
    private val autoHideDelayTime = 5 * 1000L

    /**自动隐藏延时任务*/
    private val autoHideRunnable = Runnable {
        showing = false
    }

    /** 视频画面设置对话框，并不是每个控制器都有渲染设置功能，这里做懒加载 */
    protected val surfaceSettingDialog by lazy {
        SurfaceSettingDialog(context)
    }

    /** 控制器事件处理 */
    var onControllerListener: OnControllerListener? = null
        set(value) {
            field = value
            surfaceSettingDialog.onControllerListener = field
        }

    /** 自动隐藏 */
    var autoHide = true
        set(value) {
            if (field == value) {
                return
            }
            field = value
            checkAutoHide()
        }

    /** 控制器是否正在显示 */
    var showing = false
        set(value) {
            if (field == value) {
                return
            }
            field = value
            if (field) {
                onShowController()
                checkAutoHide()
            } else {
                removeCallbacks(autoHideRunnable)
                onHideController()
            }
            onControllerListener?.onControllerShowingChanged(field)
        }

    /** 当前的VideoView */
    var mMediaPlayer: IMediaPlayer? = null

    /** 播放器状态信息监听 */
    private val playInfoListener = Observer<Long?> {
        onPlayerInfoUpdate(mMediaPlayer?.playerInfo)
    }

    /** 当前播放媒体信息监听 */
    private val mediaInfoListener = Observer<MediaInfo?> {
        onMediaInfoUpdate(mMediaPlayer?.mediaInfo)
    }

    /** 当前播放列表监听 */
    private val playListListener = Observer<ArrayList<MediaInfo>?> {
        onPlayListUpdate(mMediaPlayer?.playList?.data?.value)
    }

    /** 用户在滑动切换进度，此时进度时间由seekBar决定，不对播放器回调的时间做处理 */
    private var inUserSeek = false

    /**视图初始化，这里post一下，避免子类有变量未初始化又覆写initView导致异常。*/
    init {
        post {
            initView()
        }
    }

    /** 通过容器监听触摸事件，判断用户是否有在操作控制器 */
    override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
        val handle = super.dispatchTouchEvent(ev)
        ev?.action?.let {
            when (it) {
                MotionEvent.ACTION_DOWN -> {
                    if (handle) {
                        inUserControl = true
                    }
                }

                MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                    inUserControl = false
                }
            }
        }
        return handle
    }

    /**
     * 注册播放器监听
     */
    fun registerPlayerListener() {
        mMediaPlayer?.run {
            playerInfo?.onInfoUpdate?.observeForever(playInfoListener)
            playList?.currMedia?.observeForever(mediaInfoListener)
            playList?.data?.observeForever(playListListener)
        }
    }

    /**
     * 注销播放器监听
     */
    fun unregisterPlayerListener() {
        mMediaPlayer?.run {
            playerInfo?.onInfoUpdate?.removeObserver(playInfoListener)
            playList?.currMedia?.removeObserver(mediaInfoListener)
            playList?.data?.removeObserver(playListListener)
        }
        showing = false
        getPlayView2()?.visible()
    }

    /**
     * 控制器视图初始化
     */
    protected open fun initView() {
        //播放前一个
        getPlayPreviousView()?.setOnClickListener {
            mMediaPlayer?.playList?.playPrevious()
        }
        //播放与暂停
        getPlayView()?.setOnClickListener {
            val playing = mMediaPlayer?.playerInfo?.buttonPlaying ?: false
            if (playing) {
                mMediaPlayer?.pause()
            } else {
                mMediaPlayer?.play()
            }
        }
        //播放与暂停2
        getPlayView2()?.setOnClickListener {
            val playing = mMediaPlayer?.playerInfo?.buttonPlaying ?: false
            if (playing) {
                mMediaPlayer?.pause()
            } else {
                mMediaPlayer?.play()
            }
        }
        //播放下一个
        getPlayNextView()?.setOnClickListener {
            mMediaPlayer?.playList?.playNext()
        }
        //播放器进度条控制监听
        getProgressBar()?.run {
            setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
                override fun onProgressChanged(
                    seekBar: SeekBar?,
                    progress: Int,
                    fromUser: Boolean
                ) {
                    if (fromUser) {
                        updatePlayTime(progress * 1000L, (seekBar?.max ?: 0) * 1000L)
                    }
                }

                override fun onStartTrackingTouch(seekBar: SeekBar?) {
                    inUserSeek = true
                }

                override fun onStopTrackingTouch(seekBar: SeekBar?) {
                    inUserSeek = false
                    mMediaPlayer?.setContentProgress((seekBar?.progress ?: 0) * 1000L)
                }
            })
        }
        //更新控制器状态
        if (showing) {
            onShowController()
        } else {
            onHideController()
        }
    }

    /**
     * 播放器状态信息更新
     */
    protected open fun onPlayerInfoUpdate(playerInfo: PlayerInfo?) {
        getPlayView()?.run {
            isSelected = playerInfo?.buttonPlaying == true
        }
        getPlayView2()?.run {
            isVisible = playerInfo?.buttonPlaying != true
        }
        getProgressBar()?.run {
            max = ((playerInfo?.duration ?: 0L) / 1000).toInt()
            progress = ((playerInfo?.playProgress ?: 0L) / 1000).toInt()
            secondaryProgress = ((playerInfo?.bufferProgress ?: 0L) / 1000).toInt()
        }
        updatePlayTime(playerInfo?.playProgress, playerInfo?.duration)
    }

    /**
     * 当前播放的媒体信息更新
     */
    protected open fun onMediaInfoUpdate(mediaInfo: MediaInfo?) {}

    /**
     * 播放列表更新
     */
    protected open fun onPlayListUpdate(playList: ArrayList<MediaInfo>?) {
        if (playList.isNullOrEmpty()) {
            getPlayPreviousView()?.gone()
            getPlayNextView()?.gone()
        } else {
            getPlayPreviousView()?.visible()
            getPlayNextView()?.visible()
        }
    }

    /**
     * 显示控制器
     */
    protected open fun onShowController() {}

    /**
     * 隐藏控制器
     */
    protected open fun onHideController() {}

    /**
     * 播放上一个视图
     */
    protected open fun getPlayPreviousView(): View? {
        return null
    }

    /**
     * 播放按钮视图
     */
    protected open fun getPlayView(): View? {
        return null
    }

    /**
     * 播放按钮视图2 与[getPlayView]不同，这个播放视图在处于暂停时会显示，播放中会隐藏
     */
    protected open fun getPlayView2(): View? {
        return null
    }

    /**
     * 播放下一个视图
     */
    protected open fun getPlayNextView(): View? {
        return null
    }

    /**
     * 当前播放进度文本视图
     */
    protected open fun getProgressTextView(): TextView? {
        return null
    }

    /**
     * 播放进度条视图
     */
    protected open fun getProgressBar(): SeekBar? {
        return null
    }

    /**
     * 媒体时长视图
     */
    protected open fun getDurationTextView(): TextView? {
        return null
    }

    private fun updatePlayTime(progress: Long?, duration: Long?) {
        val displayHour = (duration ?: 0L) >= 60 * 60 * 1000L
        getProgressTextView()?.run {
            text = formatMediaTime(
                progress,
                displayHour
            )
        }
        getDurationTextView()?.run {
            text = formatMediaTime(
                duration,
                displayHour
            )
        }
    }

    /**
     * 检查状态是否允许自动隐藏
     */
    private fun checkAutoHide() {
        removeCallbacks(autoHideRunnable)
        if (autoHide && !inUserControl) {
            postDelayed(autoHideRunnable, autoHideDelayTime)
        }
    }

    /**
     * 格式化媒体时间
     *
     * @param playProgress 播放进度
     * @param displayHour 显示小时
     */
    private fun formatMediaTime(playProgress: Long?, displayHour: Boolean): String {
        val second = ((playProgress ?: 0L) / 1000).toInt()
        return if (displayHour) {
            String.format(
                "%02d:%02d:%02d",
                second / 60 / 60,
                second / 60 % 60,
                second % 60,
            )
        } else {
            String.format(
                "%02d:%02d",
                second / 60,
                second % 60,
            )
        }
    }

}
